package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.EnterpriseMaterial;
import com.ruoyi.system.domain.SupplierMaterial;
import com.ruoyi.system.domain.SupplierOrder;
import com.ruoyi.system.domain.dto.*;
import com.ruoyi.system.domain.vo.EnterpriseViewVO;
import com.ruoyi.system.mapper.*;
import org.springframework.stereotype.Service;
import com.ruoyi.system.domain.Order;
import com.ruoyi.system.service.IOrderService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 单据Service业务层处理
 *
 * @author 协同
 * @date 2022-04-18
 */
@Service
public class OrderServiceImpl implements IOrderService {
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private SupplierOrderMapper supplierOrderMapper;
    @Resource
    private EnterpriseMaterialMapper enterpriseMaterialMapper;
    @Resource
    private SupplierMaterialMapper supplierMaterialMapper;
    @Resource
    private SysUserMapper sysUserMapper;

    @Override
    public Order selectOrderById(Long id) {
        return orderMapper.selectOrderById(id);
    }

    @Override
    public List<Order> selectOrderList(Order order) {
        List<Order> orders;
        if ("3".equals(order.getType())) {
            order.setSid(SecurityUtils.getLoginUser().getUserId());
            orders = orderMapper.selectOrderList(order);
        } else {
            if ("5".equals(order.getType())) {
                order.setStatus("1");
            }
            order.setEid(SecurityUtils.getLoginUser().getUserId());
            orders = orderMapper.selectOrderList(order);
            if (orders.size() > 0) {
                if ("1".equals(order.getType())) {
                    orders.forEach(item -> {
                        List<String> collect = supplierOrderMapper.selectSupplierNameList((item.getId() + 1L)).stream().map(SupplierOrder::getSupplierName).collect(Collectors.toList());
                        if (collect.size() > 0) {
                            item.setSupplierNames(String.join(",", collect));
                        }
                    });
                } else if ("2".equals(order.getType())) {
                    orders.forEach(item -> {
                        List<String> collect = supplierOrderMapper.selectSupplierNameList(item.getId()).stream().map(SupplierOrder::getSupplierName).collect(Collectors.toList());
                        if (collect.size() > 0) {
                            item.setSupplierNames(String.join(",", collect));
                        }
                    });
                }
            }
            if (orders.size() > 0) {
                List<Order> collect = orders.stream().filter(item -> "2".equals(item.getType())).collect(Collectors.toList());
                if (collect.size() > 0) {
                    orders.forEach(item -> {
                        Order o = new Order();
                        o.setParentOrderNumber(item.getOrderNumber());
                        o.setStatus("1");
                        List<Order> list = orderMapper.selectOrderList(o);
                        if (list.size() > 0) {
                            item.setIsQuote(1);
                        } else {
                            item.setIsQuote(0);
                        }
                    });
                }
            }
        }
        return orders;
    }

    @Override
    public int insertOrder(Order order) {
        order.setCreateTime(DateUtils.getNowDate());
        order.setOrderTime(DateUtils.getNowDate());
        order.setType("1");
        order.setStatus("0");
        order.setCreateBy(SecurityUtils.getLoginUser().getUsername());
        order.setEid(SecurityUtils.getLoginUser().getUserId());
        String orderNumber = createOrderNumber("1");
        order.setOrderNumber(orderNumber);
        return orderMapper.insertOrder(order);
    }

    @Override
    public int updateOrder(Order order) {
        order.setUpdateTime(DateUtils.getNowDate());
        return orderMapper.updateOrder(order);
    }

    @Override
    public int deleteOrderByIds(Long[] ids) {
        return orderMapper.deleteOrderByIds(ids);
    }

    @Override
    public int deleteOrderById(Long id) {
        return orderMapper.deleteOrderById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int xjOrder(XJOrderDTO dto) {
        Order oldOrder = orderMapper.selectOrderById(dto.getId());
        Order newOrder = new Order();
        newOrder.setParentOrderNumber(oldOrder.getOrderNumber());
        String orderNumber = createOrderNumber("2");
        newOrder.setOrderNumber(orderNumber);
        newOrder.setType("2");
        newOrder.setStatus("0");
        newOrder.setIsPush("0");
        newOrder.setEid(oldOrder.getEid());
        newOrder.setOrderTime(DateUtils.getNowDate());
        newOrder.setNum(oldOrder.getNum());
        newOrder.setCode(oldOrder.getCode());
        newOrder.setName(oldOrder.getName());
        newOrder.setExpectedTime(oldOrder.getExpectedTime());
        orderMapper.insertOrder(newOrder);
        dto.getSupplierIds().forEach(id -> {
            SupplierOrder supplierOrder = new SupplierOrder();
            supplierOrder.setSid(id);
            supplierOrder.setOid(newOrder.getId());
            supplierOrderMapper.insertSupplierOrder(supplierOrder);
        });
        oldOrder.setIsPush("1");
        orderMapper.updateOrder(oldOrder);
        return 1;
    }

    @Override
    public int updateAllOrder(OrderDTO dto) {
        for (Long id : dto.getIds()) {
            Order order = new Order();
            order.setId(id);
            order.setStatus("1");
            updateOrder(order);
        }
        return 1;
    }

    @Override
    public int bjOrder(BJOrderDTO dto) {
        Order oldOrder = orderMapper.selectOrderById(dto.getId());
        Order newOrder = new Order();
        newOrder.setParentOrderNumber(oldOrder.getOrderNumber());
        String orderNumber = createOrderNumber("3");
        newOrder.setOrderNumber(orderNumber);
        newOrder.setStatus("0");
        newOrder.setType("3");
        newOrder.setEid(oldOrder.getEid());
        newOrder.setOrderTime(DateUtils.getNowDate());
        newOrder.setNum(oldOrder.getNum());
        newOrder.setPrice(new BigDecimal(dto.getPrice()));
        newOrder.setSid(SecurityUtils.getLoginUser().getUserId());
        newOrder.setCode(oldOrder.getCode());
        newOrder.setName(oldOrder.getName());
        newOrder.setCommitmentTime(dto.getCommitmentTime());
        orderMapper.insertOrder(newOrder);
        return 1;
    }

    @Override
    public List<Order> selectOrderXJList(Order order) {
        List<Order> orders = new ArrayList<>();
        Long userId = SecurityUtils.getLoginUser().getUserId();
        SupplierOrder supplierOrder = new SupplierOrder();
        supplierOrder.setSid(userId);
        List<SupplierOrder> supplierOrders = supplierOrderMapper.selectSupplierOrderList(supplierOrder);
        if (supplierOrders != null) {
            orders = supplierOrders.stream()
                    .map(item -> orderMapper.selectOrderById(item.getOid()))
                    .filter(o -> "1".equals(o.getStatus()) && "2".equals(order.getType()))
                    .collect(Collectors.toList());

            if (order.getOrderNumber() != null) {
                orders = orders.stream().filter(item -> order.getOrderNumber().equals(item.getOrderNumber())).collect(Collectors.toList());
            }
            if (order.getStatus() != null) {
                orders = orders.stream().filter(item -> order.getStatus().equals(item.getStatus())).collect(Collectors.toList());
            }
        }

        if (orders.size() > 0) {
            orders.forEach(item -> {
                Order o = new Order();
                o.setParentOrderNumber(item.getOrderNumber());
                o.setSid(userId);
                Optional<Order> first = orderMapper.selectOrderList(o).stream().findFirst();
                if (first.isPresent()) {
                    item.setIsQuote(1);
                }
            });
        }
        return orders;
    }

    @Override
    public List<Order> searchQuote(OrderByIdDTO dto) {
        Order o = orderMapper.selectOrderById(dto.getId());
        Order or = new Order();
        or.setParentOrderNumber(o.getOrderNumber());
        or.setType("3");
        or.setStatus("1");
        return orderMapper.selectOrderList(or);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int purchaseOrder(OrderByIdDTO dto) {
        Order BJOrder = orderMapper.selectOrderById(dto.getId());
        Order XJOrder = orderMapper.selectOrderByParentOrderNumber(BJOrder.getParentOrderNumber());
        Order order = new Order();
        order.setParentOrderNumber(XJOrder.getOrderNumber());
        order.setType("4");
        List<Order> orders = orderMapper.selectOrderList(order);
        if (orders.size() > 0) {
            throw new RuntimeException("该订单已生成采购订单无需重复操作");
        }
        String orderNumber = createOrderNumber("4");
        order.setOrderNumber(orderNumber);
        order.setStatus("0");
        order.setEid(XJOrder.getEid());
        order.setOrderTime(DateUtils.getNowDate());
        order.setCode(XJOrder.getCode());
        order.setName(XJOrder.getName());
        order.setNum(XJOrder.getNum());
        order.setSid(BJOrder.getSid());
        order.setPrice(BJOrder.getPrice());
        order.setIsPush("0");
        order.setCommitmentTime(BJOrder.getCommitmentTime());

        BJOrder.setIsPush("1");
        orderMapper.updateOrder(XJOrder);
        return orderMapper.insertOrder(order);
    }

    @Override
    public List<Order> cgList(Order order) {
        order.setType("4");
        order.setStatus("1");
        order.setSid(SecurityUtils.getLoginUser().getUserId());
        return orderMapper.selectOrderList(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addReceipt(OrderByIdDTO dto) {
        Order CGOrder = orderMapper.selectOrderById(dto.getId());
        Order sltz = new Order();
        sltz.setParentOrderNumber(CGOrder.getOrderNumber());
        sltz.setType("5");
        List<Order> orders = orderMapper.selectOrderList(sltz);
        if (orders.size() > 0) {
            throw new RuntimeException("该订单已生成收料通知订单无需重复操作");
        }
        String orderNumber = createOrderNumber("5");
        sltz.setOrderNumber(orderNumber);
        sltz.setStatus("0");
        sltz.setEid(CGOrder.getEid());
        sltz.setOrderTime(DateUtils.getNowDate());
        sltz.setCode(CGOrder.getCode());
        sltz.setName(CGOrder.getName());
        sltz.setNum(CGOrder.getNum());
        sltz.setSid(CGOrder.getSid());
        sltz.setPrice(CGOrder.getPrice());
        sltz.setIsPush("0");
        sltz.setCommitmentTime(CGOrder.getCommitmentTime());

        CGOrder.setIsPush("1");
        orderMapper.updateOrder(CGOrder);

        return orderMapper.insertOrder(sltz);
    }

    @Override
    public List<Order> sltzList(Order order) {
        order.setType("5");
        order.setSid(SecurityUtils.getLoginUser().getUserId());
        return orderMapper.selectOrderList(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int warehousing(OrderByIdDTO dto) {
        Order sltz = orderMapper.selectOrderById(dto.getId());
        Order cgrk = new Order();
        cgrk.setParentOrderNumber(sltz.getOrderNumber());
        cgrk.setType("6");
        List<Order> orders = orderMapper.selectOrderList(cgrk);
        if (orders.size() > 0) {
            throw new RuntimeException("该订单已生成采购入库订单无需重复操作");
        }
        String orderNumber = createOrderNumber("6");
        cgrk.setOrderNumber(orderNumber);
        cgrk.setStatus("0");
        cgrk.setEid(sltz.getEid());
        cgrk.setOrderTime(DateUtils.getNowDate());
        cgrk.setCode(sltz.getCode());
        cgrk.setName(sltz.getName());
        cgrk.setNum(sltz.getNum());
        cgrk.setSid(sltz.getSid());
        cgrk.setPrice(sltz.getPrice());
        cgrk.setIsPush("0");
        cgrk.setCommitmentTime(sltz.getCommitmentTime());

        sltz.setIsPush("1");
        orderMapper.updateOrder(sltz);
        return orderMapper.insertOrder(cgrk);
    }

    @Override
    public List<Order> cgrkOrder(Order order) {
        order.setType("6");
        order.setStatus("1");
        order.setSid(SecurityUtils.getLoginUser().getUserId());
        return orderMapper.selectOrderList(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int returnMaterial(ReturnOrderDTO dto) {
        Order cgrk = orderMapper.selectOrderById(dto.getId());
        Order tltz = new Order();
        tltz.setParentOrderNumber(cgrk.getOrderNumber());
        tltz.setType("7");
        List<Order> orders = orderMapper.selectOrderList(tltz);
        if (orders.size() > 0) {
            throw new RuntimeException("该订单已生成退料通知订单无需重复操作");
        }
        String orderNumber = createOrderNumber("7");
        tltz.setOrderNumber(orderNumber);
        tltz.setStatus("0");
        tltz.setEid(cgrk.getEid());
        tltz.setOrderTime(DateUtils.getNowDate());
        tltz.setCode(cgrk.getCode());
        tltz.setName(cgrk.getName());
        tltz.setNum(cgrk.getNum());
        tltz.setSid(cgrk.getSid());
        tltz.setPrice(cgrk.getPrice());
        tltz.setIsPush("0");
        tltz.setReturnNum(dto.getNum());
        tltz.setReturnTime(DateUtils.getNowDate());

        cgrk.setIsPush("1");
        orderMapper.updateOrder(cgrk);
        return orderMapper.insertOrder(tltz);
    }

    @Override
    public List<Order> tltzcxOrder(Order order) {
        order.setType("7");
        order.setStatus("1");
        order.setSid(SecurityUtils.getLoginUser().getUserId());
        return orderMapper.selectOrderList(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addPurchaseReturn(OrderByIdDTO dto) {
        Order tltz = orderMapper.selectOrderById(dto.getId());
        Order cgtl = new Order();
        cgtl.setParentOrderNumber(tltz.getOrderNumber());
        cgtl.setType("8");
        List<Order> orders = orderMapper.selectOrderList(cgtl);
        if (orders.size() > 0) {
            throw new RuntimeException("该订单已生成退料通知订单无需重复操作");
        }
        String orderNumber = createOrderNumber("8");
        cgtl.setOrderNumber(orderNumber);
        cgtl.setStatus("0");
        cgtl.setEid(tltz.getEid());
        cgtl.setOrderTime(DateUtils.getNowDate());
        cgtl.setCode(tltz.getCode());
        cgtl.setName(tltz.getName());
        cgtl.setNum(tltz.getNum());
        cgtl.setSid(tltz.getSid());
        cgtl.setPrice(tltz.getPrice());
        cgtl.setIsPush("0");
        cgtl.setReturnNum(tltz.getReturnNum());
        cgtl.setReturnTime(tltz.getReturnTime());

        tltz.setIsPush("1");
        orderMapper.updateOrder(tltz);
        return orderMapper.insertOrder(cgtl);
    }

    @Override
    public List<Order> cgtzcxOrder(Order order) {
        order.setType("8");
        order.setStatus("1");
        order.setSid(SecurityUtils.getLoginUser().getUserId());
        return orderMapper.selectOrderList(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addStock(OrderByIdDTO dto) {
        Order order = orderMapper.selectOrderById(dto.getId());
        EnterpriseMaterial enterpriseMaterial = enterpriseMaterialMapper.selectEnterpriseMaterialByCodeAndName(order.getCode(), order.getName());
        if (enterpriseMaterial != null) {
            enterpriseMaterial.setPurchaseNum(enterpriseMaterial.getPurchaseNum() + order.getNum());
            enterpriseMaterial.setExistingNum(enterpriseMaterial.getExistingNum() + order.getNum());
            enterpriseMaterialMapper.updateEnterpriseMaterial(enterpriseMaterial);
        } else {
            enterpriseMaterial = new EnterpriseMaterial();
            enterpriseMaterial.setEid(order.getEid());
            enterpriseMaterial.setCode(order.getCode());
            enterpriseMaterial.setName(order.getName());
            enterpriseMaterial.setInitialNum(0);
            enterpriseMaterial.setPurchaseNum(order.getNum());
            enterpriseMaterial.setReturnNum(0);
            enterpriseMaterial.setNormalNum(0);
            enterpriseMaterial.setExistingNum(order.getNum());
            enterpriseMaterialMapper.insertEnterpriseMaterial(enterpriseMaterial);
        }

        SupplierMaterial supplierMaterial = supplierMaterialMapper.selectSupplierMaterialByCodeAndName(order.getCode(), order.getName());
        if (supplierMaterial != null) {
            supplierMaterial.setPurchase(supplierMaterial.getPurchase() - order.getNum());
            supplierMaterial.setExisting(supplierMaterial.getExisting() - order.getNum());
            supplierMaterialMapper.updateSupplierMaterial(supplierMaterial);
        }

        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateStock(OrderByIdDTO dto) {
        Order order = orderMapper.selectOrderById(dto.getId());
        int num = order.getNum() - order.getReturnNum();
        order.setNum(num);
        orderMapper.updateOrder(order);

        Order parentOrder = orderMapper.selectOrderByParentOrderNumber(order.getParentOrderNumber());
        parentOrder.setNum(num);
        orderMapper.updateOrder(parentOrder);

        EnterpriseMaterial enterpriseMaterial = enterpriseMaterialMapper.selectEnterpriseMaterialByCodeAndName(order.getCode(), order.getName());
        if (enterpriseMaterial != null) {
            enterpriseMaterial.setReturnNum(enterpriseMaterial.getReturnNum() + order.getReturnNum());
            enterpriseMaterial.setExistingNum(enterpriseMaterial.getExistingNum() - order.getReturnNum());
            enterpriseMaterialMapper.updateEnterpriseMaterial(enterpriseMaterial);
        }

        SupplierMaterial supplierMaterial = supplierMaterialMapper.selectSupplierMaterialByCodeAndName(order.getCode(), order.getName());
        if (supplierMaterial != null) {
            supplierMaterial.setReturnMaterial(supplierMaterial.getReturnMaterial() + order.getReturnNum());
            supplierMaterial.setExisting(supplierMaterial.getExisting() + order.getNum());
            supplierMaterialMapper.updateSupplierMaterial(supplierMaterial);
        } else {
            supplierMaterial = new SupplierMaterial();
            supplierMaterial.setSupplierId(order.getSid());
            supplierMaterial.setCode(order.getCode());
            supplierMaterial.setName(order.getName());
            supplierMaterial.setProduction(order.getReturnNum() + order.getNum());
            supplierMaterial.setReturnMaterial(order.getReturnNum());
            supplierMaterial.setPurchase(order.getNum());
            supplierMaterial.setExisting(0);
            supplierMaterialMapper.insertSupplierMaterial(supplierMaterial);
        }

        return 1;
    }

    @Override
    public List<Order> getEnterpriseList(Order order) {
        List<Order> orders = new ArrayList<>();

        EnterpriseMaterial enterpriseMaterial = enterpriseMaterialMapper.selectEnterpriseMaterialById(order.getMaterialId());

        order.setCode(enterpriseMaterial.getCode());
        order.setName(enterpriseMaterial.getName());

        order.setStatus("1");
        order.setEid(SecurityUtils.getLoginUser().getUserId());

        // 采购订单
        order.setType("4");
        List<Order> cgOrder = orderMapper.selectOrderList(order);
        if (cgOrder.size() > 0) {
            orders.addAll(cgOrder);
        }

        // 采购退料单
        order.setType("8");
        List<Order> tlOrder = orderMapper.selectOrderList(order);
        if (tlOrder.size() > 0) {
            orders.addAll(tlOrder);
        }
        return orders;
    }

    @Override
    public List<Order> getSupplierList(Order order) {
        List<Order> orders = new ArrayList<>();

        SupplierMaterial supplierMaterial = supplierMaterialMapper.selectSupplierMaterialById(order.getMaterialId());

        order.setCode(supplierMaterial.getCode());
        order.setName(supplierMaterial.getName());

        order.setStatus("1");
        order.setSid(SecurityUtils.getLoginUser().getUserId());

        // 采购订单
        order.setType("4");
        List<Order> cgOrder = orderMapper.selectOrderList(order);
        if (cgOrder.size() > 0) {
            orders.addAll(cgOrder);
        }

        // 采购退料单
        order.setType("8");
        List<Order> tlOrder = orderMapper.selectOrderList(order);
        if (tlOrder.size() > 0) {
            orders.addAll(tlOrder);
        }
        return orders;
    }

    @Override
    public EnterpriseViewVO getEnterpriseView(Order order) {
        EnterpriseViewVO vo = new EnterpriseViewVO();
        List<BigDecimal> priceData = new ArrayList<>();
        List<String> dateData = new ArrayList<>();
        List<String> supplierData = new ArrayList<>();
        EnterpriseMaterial enterpriseMaterial = enterpriseMaterialMapper.selectEnterpriseMaterialById(order.getMaterialId());
        order.setCode(enterpriseMaterial.getCode());
        order.setName(enterpriseMaterial.getName());
        order.setStatus("1");
        order.setEid(SecurityUtils.getLoginUser().getUserId());
        order.setType("4");
        List<Order> orders = orderMapper.selectOrderList(order);
        if (orders.size() > 0) {
            orders.forEach(item -> {
                priceData.add(item.getPrice());
                dateData.add(DateUtils.dateTime(item.getOrderTime()));
                SysUser sysUser = sysUserMapper.selectUserById(item.getSid());
                supplierData.add(sysUser.getUserName());
            });
        }
        vo.setPriceData(priceData);
        vo.setDateData(dateData);
        vo.setSupplierData(supplierData);
        return vo;
    }

    @Override
    public EnterpriseViewVO getSupplierView(Order order) {
        EnterpriseViewVO vo = new EnterpriseViewVO();
        List<BigDecimal> priceData = new ArrayList<>();
        List<String> dateData = new ArrayList<>();
        List<String> enterpriseData = new ArrayList<>();
        SupplierMaterial supplierMaterial = supplierMaterialMapper.selectSupplierMaterialById(order.getMaterialId());
        order.setCode(supplierMaterial.getCode());
        order.setName(supplierMaterial.getName());
        order.setStatus("1");
        order.setSid(SecurityUtils.getLoginUser().getUserId());
        order.setType("4");
        List<Order> orders = orderMapper.selectOrderList(order);
        if (orders.size() > 0) {
            orders.forEach(item -> {
                priceData.add(item.getPrice());
                dateData.add(DateUtils.dateTime(item.getOrderTime()));
                SysUser sysUser = sysUserMapper.selectUserById(item.getEid());
                enterpriseData.add(sysUser.getUserName());
            });
        }
        vo.setPriceData(priceData);
        vo.setDateData(dateData);
        vo.setEnterpriseData(enterpriseData);
        return vo;
    }

    /**
     * 生成订单号
     */
    private static String createOrderNumber(String type) {
        //前缀(单据类型(1采购申请单 2询价单 3报价单 4采购订单 5收料通知单 6采购入库单 7退料通知单 8采购退料单))
        String front = null;
        switch (type) {
            case "1":
                front = "CGSQD";
                break;
            case "2":
                front = "XJD";
                break;
            case "3":
                front = "BJD";
                break;
            case "4":
                front = "CGD";
                break;
            case "5":
                front = "SLTZD";
                break;
            case "6":
                front = "CGRKD";
                break;
            case "7":
                front = "TLTZD";
                break;
            case "8":
                front = "CGTLD";
                break;
            default:
                break;
        }
        String orderNo;

        Date nowDate = new Date();

        Random random = new Random();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

        StringBuilder fourRandom = new StringBuilder(random.nextInt(9999) + "");

        int randLength = fourRandom.length();

        //四位随机数，不足四位的补0
        //不足四位的随机数补充0
        if (fourRandom.length() < 4) {
            for (int i = 1; i <= 4 - randLength; i++) {
                fourRandom.insert(0, '0');
            }
        }

        orderNo = front + sdf.format(nowDate) + fourRandom;

        return orderNo;
    }
}
